import os
from fastapi import FastAPI, Request, Form
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
from fastapi.responses import JSONResponse
import docker_operations
import asyncio
import json
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger

# 配置日志
from utils.logger import logger

# 定义lifespan函数替代@app.on_event
async def lifespan(app: FastAPI):
    # 应用启动时执行的代码
    scheduler.start()
    logger.info("应用启动，调度器已启动")

    # 添加定时任务
    scheduler.add_job(
        trigger_update_registry,
        # CronTrigger(minute='*/1'),  # 每分钟触发一次
        CronTrigger(hour=2, minute=0),  # 每天凌晨2点执行
        id='update_registry',
        name='更新注册表信息',
        replace_existing=True
    )

    yield

    # 应用关闭时执行的代码
    scheduler.shutdown()
    logger.info("应用关闭，调度器已关闭")


app = FastAPI(title="CTYun Docker Registry UI", lifespan=lifespan)
templates = Jinja2Templates(directory="templates")

# 确保静态文件目录存在
static_dir = "static"
if not os.path.exists(static_dir):
    os.makedirs(static_dir)
    logger.info(f"Created static directory: {static_dir}")

app.mount("/static", StaticFiles(directory=static_dir), name="static")

# 创建调度器
scheduler = AsyncIOScheduler()

import subprocess

def get_poetry_venv_path():
    """动态获取Poetry虚拟环境路径"""
    try:
        result = subprocess.run(
            ["poetry", "env", "info", "--path"],
            capture_output=True,
            text=True,
            check=True
        )
        return result.stdout.strip() + "/bin/python"
    except subprocess.CalledProcessError as e:
        logger.error(f"获取Poetry虚拟环境路径失败: {e.stderr}")
        # 返回默认路径或抛出异常
        raise RuntimeError("无法获取Poetry虚拟环境路径")


async def trigger_update_registry():
    """定时更新注册表信息"""
    try:
        logger.info("开始定时更新注册表信息")

        # 动态获取虚拟环境Python路径
        venv_python = get_poetry_venv_path()
        logger.info(f"使用Python解释器: {venv_python}")

        # 构建完整脚本路径（假设test_selenium.py在项目根目录）
        project_root = os.path.dirname(os.path.abspath(__file__))
        script_path = os.path.join(project_root, "test_selenium.py")

        result = subprocess.run(
            [venv_python, script_path],
            capture_output=True,
            text=True,
            check=True,
            cwd=project_root  # 设置工作目录
        )

        logger.info("注册表信息更新成功")
        logger.info(f"输出: {result.stdout}")

    except subprocess.CalledProcessError as e:
        logger.error("注册表信息更新失败")
        logger.error(f"错误: {e.stderr}")
    except Exception as e:
        logger.error(f"更新过程中发生错误: {str(e)}")



@app.get("/")
async def home(request: Request):
    # 读取登录信息
    try:
        with open("docker_login_info.txt", "r", encoding="utf-8") as f:
            login_info = f.read().splitlines()
    except:
        login_info = []
        
    # 读取镜像列表
    try:
        with open("image_list.json", "r", encoding="utf-8") as f:
            image_list = json.load(f)
    except:
        image_list = []
        
    return templates.TemplateResponse(
        "index.html",
        {
            "request": request,
            "login_info": login_info,
            "image_list": image_list
        }
    )

@app.post("/push-image")
async def push_image(
    image_name: str = Form(...),
    tag: str = Form(...),
):
    try:
        # 创建 DockerOperations 实例
        docker_ops = docker_operations.DockerOperations(org_name="robert")
        
        # 异步执行推送操作
        success = await asyncio.to_thread(
            docker_ops.push_image,
            image_name,
            tag
        )
        
        if success:
            return JSONResponse({
                "status": "success",
                "message": f"成功推送镜像 {image_name}:{tag}"
            })
        else:
            return JSONResponse({
                "status": "error",
                "message": "推送失败，请检查日志"
            }, status_code=500)
            
    except Exception as e:
        logger.error(f"推送镜像时发生错误: {str(e)}")
        return JSONResponse({
            "status": "error",
            "message": f"发生错误: {str(e)}"
        }, status_code=500)

@app.get("/health")
async def health_check():
    return {"status": "healthy"}

# 添加手动触发更新的接口
@app.post("/trigger-update")
async def trigger_update():
    try:
        await update_registry()
        return {"status": "success", "message": "更新任务已触发"}
    except Exception as e:
        return {"status": "error", "message": str(e)} 